package ffte.test.types

import spinal.core._
import spinal.core.sim._
import ffte.types._

/**
 * 最简单的FFTE类型使用示例
 * 用于理解FFTE类型作为硬件信号的本质
 */
class SimplestFixRealExample extends Component {
  val io = new Bundle {
    val input = in SInt(16 bits)  // 普通硬件输入
    val output = out SInt(16 bits) // 普通硬件输出 - 修正宽度匹配
    val enable = in Bool()         // 使能信号
  }

  // 使用FixReal类型的最简单示例
  val testArea = new Area {
    // 创建一个FixReal实例 - 这代表硬件中的实际信号
    val myFixReal = FixReal(16, -8)  // 16位总宽度，8位小数位
    
    // 当使能信号有效时，进行操作
    when(io.enable) {
      // 将输入的SInt解释为FixReal的值
      myFixReal.d.raw := io.input
      
      // 执行简单的加法操作 - 这会创建实际的硬件连接
      val doubled = myFixReal + myFixReal  // 硬件加法器
      
      // 输出结果 - 需要处理位宽差异
      io.output := doubled.d.raw.resized
    } otherwise {
      io.output := 0
    }
  }
}

/**
 * 仿真测试 - 验证硬件行为
 */
object SimplestFixRealExampleSim {
  def main(args: Array[String]): Unit = {
    // 编译并仿真
    SimConfig.withWave.compile(new SimplestFixRealExample()).doSim { dut =>
      
      // 创建时钟域
      dut.clockDomain.forkStimulus(period = 10)
      
      // 测试序列
      println("开始SimplestFixRealExample仿真...")
      
      // 测试1: 输入0.5（定点表示）
      dut.io.enable #= true
      dut.io.input #= Math.round(0.5 * 128)  // 0.5 * 2^8
      dut.clockDomain.waitSampling(1)
      
      val output1 = dut.io.output.toInt
      val expected1 = Math.round(1.0 * 128)  // 0.5 + 0.5 = 1.0
      println(f"测试1: 输入0.5，输出$output1，期望$expected1")
      
      // 测试2: 输入0.25
      dut.io.input #= Math.round(0.25 * 128)
      dut.clockDomain.waitSampling(1)
      
      val output2 = dut.io.output.toInt
      val expected2 = Math.round(0.5 * 128)  // 0.25 + 0.25 = 0.5
      println(f"测试2: 输入0.25，输出$output2，期望$expected2")
      
      // 测试3: 禁用使能
      dut.io.enable #= false
      dut.io.input #= Math.round(0.1 * 128)
      dut.clockDomain.waitSampling(1)
      
      val output3 = dut.io.output.toInt
      println(f"测试3: 禁用使能，输出$output3，期望0")
      
      println("仿真完成！")
    }
  }
}

/**
 * 观察FixReal作为硬件信号的本质
 */
class FixRealNatureDemo extends Component {
  val io = new Bundle {
    val in1 = in SInt(16 bits)
    val in2 = in SInt(16 bits)
    val out_add = out SInt(16 bits)  // 加法结果
    val out_mul = out SInt(32 bits)  // 乘法结果（位宽增长）
    val out_resize = out SInt(24 bits) // 调整大小结果
  }

  val demoArea = new Area {
    // 创建FixReal实例 - 这些是硬件信号，不是普通变量
    val a = FixReal(16, -8)
    val b = FixReal(16, -8)
    
    // 连接输入
    a.d.raw := io.in1
    b.d.raw := io.in2
    
    // 执行操作 - 这些创建硬件连接，不是内存计算
    val sum = a + b        // 创建加法器硬件
    val product = a * b    // 创建乘法器硬件（位宽增长）
    val resized = a.resize(24) // 创建位宽调整硬件
    
    // 连接输出
    io.out_add := sum.d.raw
    io.out_mul := product.d.raw
    io.out_resize := resized.d.raw
  }
}

object FixRealNatureDemoSim {
  def main(args: Array[String]): Unit = {
    SimConfig.withWave.compile(new FixRealNatureDemo()).doSim { dut =>
      dut.clockDomain.forkStimulus(period = 10)
      
      println("开始FixRealNatureDemo仿真...")
      
      // 测试不同的操作
      dut.io.in1 #= Math.round(0.5 * 128)
      dut.io.in2 #= Math.round(0.3 * 128)
      dut.clockDomain.waitSampling(1)
      
      println(f"输入1: 0.5, 输入2: 0.3")
      println(f"加法结果: ${dut.io.out_add.toInt} (${dut.io.out_add.toInt / 128.0})")
      println(f"乘法结果: ${dut.io.out_mul.toInt} (${dut.io.out_mul.toInt / (128.0 * 128.0)})")
      println(f"调整大小结果: ${dut.io.out_resize.toInt} (${dut.io.out_resize.toInt / 128.0})")
      
      println("观察：")
      println(s"- 加法保持相同的定点精度: 0.5 + 0.3 = 0.8")
      println(s"- 乘法精度翻倍: 0.5 * 0.3 = 0.15")
      println(s"- resize只是改变位宽，不改变数值")
      
      println("\n关键理解：")
      println("1. FixReal.d.raw 是对底层SFix信号的引用")
      println("2. 算术运算创建实际的硬件连接，不是内存计算")
      println("3. 位宽管理是硬件设计的一部分")
      println("4. 仿真时我们看到的是硬件信号的行为")
    }
  }
}